<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\Common\Constants\GenderConstants;
use App\Common\Service\ExcelService;
use App\CustHub\Amqp\Producers\SyncTaskProducers;
use App\CustHub\Constants\ContactBehaviorTypeConstants;
use App\CustHub\Constants\ContactSourceConstants;
use App\CustHub\Constants\ContactStatusConstants;
use App\CustHub\Constants\ContactTaskCenterTyperConstants;
use App\CustHub\Constants\SyncTaskStatusConstants;
use App\CustHub\Constants\SyncTaskTypeConstants;
use App\CustHub\Dto\ContactTcContentDto;
use App\CustHub\Dto\SyncTaskDto;
use App\CustHub\Event\ContactOperationBehaviorAfter;
use App\CustHub\Event\SopTagTrigger;
use App\CustHub\Helpers\Robot;
use App\CustHub\Helpers\TagReplacer;
use App\CustHub\Mapper\ChContactMapper;
use App\CustHub\Mapper\ChCorpMapper;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Mapper\ChSyncTaskMapper;
use App\CustHub\Model\ChContact;
use App\CustHub\Model\ChContactBehaviorLog;
use App\CustHub\Model\ChContactMobile;
use App\CustHub\Model\ChCorp;
use App\CustHub\Model\ChCorpTag;
use App\CustHub\Model\ChRobot;
use App\CustHub\Model\ChRoom;
use App\CustHub\Model\ChRoomMember;
use App\CustHub\Model\ChSyncTask;
use App\Robot\Service\RobotApiService;
use Carbon\Carbon;
use Hyperf\Amqp\Producer;
use Hyperf\Collection\Collection;
use Hyperf\Coroutine\Coroutine;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use Mine\MineModel;
use Psr\EventDispatcher\EventDispatcherInterface;
use function Hyperf\Collection\collect;
use function Hyperf\Collection\data_get;
use function Hyperf\Coroutine\co;
use function Hyperf\Support\call;

class ChContactService extends AbstractService
{
    public $mapper;

    #[Inject]
    protected ChRobotMapper $robotMapper;

    #[Inject]
    protected ChCorpMapper $corpMapper;

    #[Inject]
    protected ChSyncTaskMapper $syncTaskMapper;

    #[Inject]
    private EventDispatcherInterface $eventDispatcher;


    public function __construct(ChContactMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    public function getContactList(array $data): array
    {
        $pageSize = $data['page_size'] ?? MineModel::PAGE_SIZE;

        $query = $this->mapper->model::query()
            ->select(['id', 'robot_id', 'gender', 'real_name', 'remark', 'nickname', 'alias', 'call_name', 'create_time', 'add_customer_time', 'mobile', 'avatar', 'corp_short_name', 'corp_name', 'group_id', 'user_id', 'source', 'desc', 'status', 'is_wechat', 'last_send_msg_time','friend_loss_time','is_white','is_black']);

        $data['robot_ids'] = !empty($data['robot_id']) ? [$data['robot_id']] : [];
        $paginate = $this->mapper
            ->handleSearch($query, $data)
            ->orderBy('add_customer_time', 'desc')
            ->paginate((int)$pageSize);

        $paginate->getCollection()->transform(function ($item) {
            $item->gender_text = GenderConstants::getMessage($item->gender);
            $item->source_text = ContactSourceConstants::getMessage($item->source);
            $item->status_text = ContactStatusConstants::getMessage($item->status);
            $item->add_customer_time_text = datetime($item->add_customer_time);
            return $item;
        });

        $result = $this->mapper->setPaginate($paginate);
        $unique_count = $this->mapper->getUniqueContactCount($data);
        $result['unique_count'] = $unique_count;
        return $result;
    }

    public function exportContacts(array $params)
    {
        $params['robot_ids'] = !empty($params['robot_id']) ? [$params['robot_id']] : [];

        if(!empty($params['export_fields'])){
            $exportFields = json_decode($params['export_fields'],true);
        }else{
            $exportFields = [
                'nickname',
                'gender_text',
                'call_name',
                'robot_nickname',
                'add_customer_time_text',
                'corp_tag',
                'smart_tag',
                'source_text',
                'status_text',
                'friend_loss_time',
                'last_send_msg_time',
            ];
        }

        $headerData = [
            'nickname'=> [
                'value' => '客户'
            ],
            'gender_text' => [
                'value' => '性别',
            ],
            'call_name'=> [
                'value' => '称呼'
            ],
            'robot_nickname'=> [
                'value' => '所属企微号'
            ],
            'add_customer_time_text'=> [
                'value' => '添加时间'
            ],
            'corp_tag'=> [
                'value' => '企微标签'
            ],
            'smart_tag'=> [
                'value' => '智能标签'
            ],
            'source_text'=> [
                'value' => '客户来源'
            ],
            'status_text'=> [
                'value' => '好友关系'
            ],
            'friend_loss_time'=> [
                'value' => '流失时间'
            ],
            'last_send_msg_time'=> [
                'value' => '最后发言时间'
            ],
        ];

        foreach ($headerData as $k=>$headerItem){
            if(!in_array($k,$exportFields)){
                unset($headerData[$k]);
            }
        }

        $query = $this->mapper->model::query()
            ->select(['id', 'robot_id','nickname', 'gender', 'call_name', 'add_customer_time', 'status','source', 'friend_loss_time', 'last_send_msg_time']);

        $list = $this->mapper
            ->handleSearch($query, $params)
            ->get();

        $list = $list->map(function ($item) use ($exportFields) {

            $item->gender_text = GenderConstants::getMessage($item->gender);
            $item->source_text = ContactSourceConstants::getMessage($item->source);
            $item->status_text = ContactStatusConstants::getMessage($item->status);
            $item->add_customer_time_text = datetime($item->add_customer_time);
            $item->robot_nickname = $item->robot->nickname ?? '';
            $item->corp_tag = $item->corpTags->pluck('name')->implode(',');
            $item->smart_tag = $item->smartTags->pluck('name')->implode(',');

            return $item;
        })->toArray();
        $excelService = new ExcelService($headerData);
        return $excelService->export('客户数据'.Carbon::now()->toDateTimeString(),$list);
    }

    /**
     * 获取联系人列表
     * @param array $params
     * @return array
     */
    public function getContactsByFilter(array $params, array $fields = ['*'],bool $isLoad = true): array
    {
        return $this->mapper->handleSearch($this->mapper->model::query()->select($fields), $params,$isLoad)
            ->get()
            ->toArray();
    }

    /**
     * 加入黑名单
     * @param array $data
     * @return bool
     */
    public function addToBlacklist(array $data): bool
    {
        $contact = $this->mapper->findById($data['id']);
        if (empty($contact)) {
            throw new NormalStatusException('请选择客户');
        }

        $data['user_ids'] = [$contact->user_id];
        return container()->get(ChContactBlackService::class)->saveBlack($data);
    }

    /**
     * 获取联系人详情
     * @param array $params
     * @return array
     */
    public function getInfo(array $params): array
    {
        $contact = $this->mapper->findById($params['id']);
        if (empty($contact)) {
            throw new NormalStatusException('请选择客户');
        }

        $corpTagNames = $contact->corpTags()->where('label_type', 1)->pluck('name')->toArray();
        $smartTagNames = $contact->smartTags()->pluck('name')->toArray();

        $contactInfo = [
            'id' => $contact->id,
            'nickname' => $contact->nickname,
            'avatar' => $contact->avatar,
            'corp_short_name' => $contact->corp_short_name,
            'corp_name' => $contact->corp_name,
            'is_wechat' => $contact->is_wechat,
            'corp_tag_names' => $corpTagNames,
            'smart_tag_names' => $smartTagNames,
            'gender' => $contact->gender,
            'user_id' => $contact->user_id
        ];

        $robotContactList = $this->mapper->model::query()
            ->select(['id', 'robot_id', 'remark', 'call_name', 'create_time', 'source', 'company_remark', 'desc', 'gender'])
            ->with(['robot' => function ($query) {
                $query->select(['id', 'nickname', 'avatar','corp_id', 'corp_name', 'login_status']);
            }, 'corpTags' => function ($query) {
                $query->select(['id', 'name', 'label_type']);
            }, 'smartTags' => function ($query) {
                $query->select(['id', 'name']);
            }, 'mobileList'])
            ->withPermission((int)$params['uid'])
            ->where('user_id', $contact->user_id)
            ->get()->toArray();

        foreach ($robotContactList as $k => $item) {
            $robotContactList[$k]['create_time'] = datetime($item['create_time']);
            $robotContactList[$k]['source'] = ContactSourceConstants::getMessage($item['source']);

            $corpTags = $item['corp_tags'];
            $personalTags = [];
            foreach ($corpTags as $ck => $corpTagItem) {
                if ($corpTagItem['label_type'] == 2) {
                    $personalTags[] = $corpTagItem;
                    unset($corpTags[$ck]);
                }
            }

            $robotContactList[$k]['corp_tags'] = array_values($corpTags);
            $robotContactList[$k]['personal_tags'] = $personalTags;
        }

        return [
            'baseInfo' => $contactInfo,
            'robot_contact_list' => $robotContactList
        ];
    }

    /**
     * 用户行为日志
     * @param array $params
     * @return array
     */
    public function behaviorLog(array $params): array
    {
        $pageSize = $params['page_size'] ?? MineModel::PAGE_SIZE;
        $result = ChContactBehaviorLog::query()
            ->select(['id', 'remark', 'created_at'])
            ->where('contact_id', $params['id'])
            ->orderBy('created_at', 'desc')
            ->paginate((int)$pageSize);
        return $this->mapper->setPaginate($result);
    }

    public function getUserRooms(array $params): array
    {
        $userId = $params['user_id'];
        $is_out = $params['is_out'];
        $pageSize = $params['page_size'] ?? MineModel::PAGE_SIZE;
        $result = ChRoomMember::query()
            ->select(['id', 'room_wxid', 'join_time', 'out_time'])
            ->with(['room' => function ($query) {
                $query->select(['id', 'room_wxid', 'room_name', 'room_avatar_url', 'room_member_count', 'room_owner_name'])
                    ->with(['robots' => function ($query) {
                        $query->select(['id', 'nickname']);
                    }]);
            }])
            ->where('user_id', $userId)
            ->where('is_out', $is_out)
            ->paginate((int)$pageSize);

        $result->getCollection()->transform(function ($item) {
            $item->join_time_text = datetime($item->join_time);
            return $item;
        });

        return $this->mapper->setPaginate($result);
    }


    public function syncContact(array $params): bool
    {
        $robotIds = json_decode($params['robot_ids']);
        foreach ($robotIds as $robotId){
            $this->addSyncTask($robotId);
        }
        return true;
    }

    /**
     * 添加同步任务
     * @param $robotId
     * @return bool
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function addSyncTask($robotId): bool
    {
        $type = SyncTaskTypeConstants::CONTACTS;
        $robotInfo = $this->robotMapper->findById($robotId);
        //检查是否存在进行中的任务
        if($this->syncTaskMapper->checkIsTaskInProgress($robotId,$type)){
//            throw new NormalStatusException('客户在同步中，请稍后再试');
            return false;
        }

        $currentSeq = $this->syncTaskMapper->getLatestCurrentSeq($robotId,$type);

        $syncTaskData = [
            'uid' => $robotInfo['uid'],
            'main_uid' => $robotInfo['main_uid'],
            'corp_id' => $robotInfo['corp_id'],
            'robot_id' => $robotInfo['id'],
            'type' => $type,
            'status' => SyncTaskStatusConstants::RUNNING,
            'start_time' => time(),
        ];

//        $syncTaskId = $this->syncTaskMapper->save($syncTaskData);

        $info = ChSyncTask::create($syncTaskData);

        co(function () use ($info){
            try {
                container()->get(ChContactSyncService::class)->batchSyncContacts($info);
            }catch (\Throwable $throwable){
                ChSyncTask::query()
                    ->where('id',$info->id)
                    ->update([
                        'status' => SyncTaskStatusConstants::FAILURE,
                        'failure_reason' => $throwable->getMessage(),
                        'end_time' => time()
                    ]);
            }
        });
        return true;
//        return container()->get(Producer::class)->produce(new SyncTaskProducers(new SyncTaskDto(
//            taskId: $syncTaskId,
//            type: $type,
//            className: ChContactSyncService::class,
//            method: 'batchSyncContacts',
//            currentSeq: 0
//        )));
    }


    /**
     * 客户企业标签，新增删除
     * @param $contactList
     * @param array $tagIds
     * @param bool $isAddTag
     * @return int
     */
    public function tagMemberOp($contactList, array $tagIds, bool $isAddTag = true): int
    {
        $finishedContactCount = 0;
        if (empty($contactList) || empty($tagIds)) {
            return $finishedContactCount;
        }

        $tagMap = ChCorpTag::query()
            ->select(['id', 'group_id', 'corp_id', 'owner_id', 'label_type'])
            ->whereIn('id', $tagIds)
            ->get()->toArray();

        $labelIdList = [];
        $labelSuperIdList = [];
        $labelOwnerList = [];
        foreach ($tagMap as $k => $item) {
            $labelIdList[$k] = $item['id'];
            $labelSuperIdList[$k] = $item['group_id'];
            $labelOwnerList[$k] = $item['owner_id'];
        }

        $contactMap = $contactList->groupBy('robot_id')->toArray();
        $opType = $isAddTag ? 1 : 2;
        foreach ($contactMap as $robotId => $contactItems) {
            $robotInfo = $this->robotMapper->findById($robotId);
            if (!$robotInfo['login_status']) {
                continue;
            }
            $paramList = [];
            foreach ($contactItems as $contact) {
                $paramList[] = [
                    'labelIdList' => $labelIdList,
                    'labelSuperIdList' => $labelSuperIdList,
                    'labelOwnerList' => $labelOwnerList,
                    'userId' => $contact['user_id']
                ];
            }
            $robotApiService = make(\App\Common\Robot\Robot::class, [$robotInfo->server_id, $robotInfo->uuid])->gateway();
            $rst = $robotApiService->contactEditLabel($opType, $paramList);
            if ($rst !== false) {
                //操作成功
                $finishedContactCount = $finishedContactCount + count($contactItems);
            }
            //延迟3秒触发标签sop
            co(function () use ($contactList) {
                Coroutine::sleep(3);
                foreach ($contactList as $contact){
                    $contact = $this->mapper->findById($contact['id']);
                    $this->eventDispatcher->dispatch(new SopTagTrigger($contact));
                }
            });
        }
        return $finishedContactCount;
    }

    public function getContactByUserIds($ids)
    {
        return $this->mapper->getModel()->newQuery()->whereIn('user_id', $ids)->distinct()->select(['nickname', 'avatar', 'user_id', 'corp_short_name', 'is_wechat'])->get()->toArray();
    }

    /**
     * 获取未流失好友
     * @param $robotId
     * @param $ids
     * @return Collection
     */
    public function getContactNotLoss($robotId,$ids)
    {
        return $this->mapper->getModel()->newQuery()->where('robot_id',$robotId)->whereIn('user_id', $ids)->where('status',ContactStatusConstants::NORMAL_FRIEND)->pluck('user_id');
    }


    /**
     * 修改客户备注
     * @param array $data
     * @return bool
     */
    public function editRemark(array $data): bool
    {
        return $this->performEditAction($data, function ($robotApiService, $contact, $mobileList, $labelList) use ($data) {
            return $robotApiService->updateWxContact(
                $contact->user_id,
                $data['remark'],
                $contact->desc,
                $contact->company_remark,
                $mobileList,
                $labelList
            );
        });
    }

    /**
     * 修改手机号
     * @param array $data
     * @return bool
     */
    public function editMobile(array $data): bool
    {
        $mobile = json_decode($data['mobile'], true);
        return $this->performEditAction($data, function ($robotApiService, $contact, $mobileList, $labelList) use ($mobile) {
            return $robotApiService->updateWxContact(
                $contact->user_id,
                $contact->remark,
                $contact->desc,
                $contact->company_remark,
                $mobile,
                $labelList
            );
        });
    }

    /**
     * 修改描述
     * @param array $data
     * @return bool
     */
    public function editDesc(array $data): bool
    {
        return $this->performEditAction($data, function ($robotApiService, $contact, $mobileList, $labelList) use ($data) {
            return $robotApiService->updateWxContact(
                $contact->user_id,
                $contact->remark,
                $data['desc'],
                $contact->company_remark,
                $mobileList,
                $labelList
            );
        });
    }

    /**
     * 修改公司备注
     * @param array $data
     * @return bool
     */
    public function editCompanyRemark(array $data): bool
    {
        return $this->performEditAction($data, function ($robotApiService, $contact, $mobileList, $labelList) use ($data) {
            return $robotApiService->updateWxContact(
                $contact->user_id,
                $contact->remark,
                $contact->desc,
                $data['company_remark'],
                $mobileList,
                $labelList
            );
        });
    }


    /**
     * 执行修改动作
     * @param array $data
     * @param callable $callback
     * @return bool
     */
    private function performEditAction(array $data, callable $callback): bool
    {
        $contact = $this->mapper->findById($data['id']);
        if (empty($contact)) {
            throw new NormalStatusException('请选择客户');
        }

        $robotInfo = $this->robotMapper->findById($contact->robot_id);
        if (empty($robotInfo) || $robotInfo->login_status != 1) {
            throw new NormalStatusException('请先登录机器人');
        }

        $mobileList = ChContactMobile::query()->where('contact_id', $contact->id)->pluck('mobile')->toArray();
        $labelList = $contact->corpTags()->get();

        $labelList = $labelList->map(function ($item) {
            return [
                'group_id' => $item['group_id'],
                'label_id' => $item['id'],
                'label_type' => $item['label_type'],
                'owner_id' => $item['owner_id'],
            ];
        })->toArray();

        $robotApiService = make(\App\Common\Robot\Robot::class, [$robotInfo->server_id, $robotInfo->uuid])->gateway();
        $result = $callback($robotApiService, $contact, $mobileList,$labelList);
        $this->mapper->rmCache($contact->robot_id,$contact->user_id);
        return $result !== false;
    }


    /**
     * 修改客户称呼
     * @param array $data
     * @return bool
     */
    public function editCallName(array $data): bool
    {
        $contact = $this->mapper->findById($data['id']);
        if (empty($contact)) {
            throw new NormalStatusException('请选择客户');
        }
        $contact->call_name = $data['call_name'];
        $rst = $contact->save();
        if($rst){
            $this->mapper->rmCache($contact->robot_id,$contact->user_id);
        }
        return $rst;
    }

    /**
     * 设置企业标签
     * @param array $data
     * @return bool
     */
    public function setCorpTag(array $data): bool
    {
        $corpTagIds = json_decode($data['corp_tag_ids'], true);
        return $this->commonSetCorpTag($data['id'], $corpTagIds, 1);
    }

    /**
     * 批量设置企业标签
     * @param array $data
     * @return bool
     */
    public function batchSetCorpTag(array $data): bool
    {
        $corpTagIds = json_decode($data['corp_tag_ids'], true);
        $ids = json_decode($data['ids'], true);

        $content = new ContactTcContentDto();
        $content->setContactIds($ids);
        $content->setTagIds($corpTagIds);

        return container()->get(ChContactTaskCenterService::class)->addTask($data['uid'],$data['main_uid'],ContactTaskCenterTyperConstants::PUT_ON_CORP_TAG,$content);
    }

    /**
     * 批量移除企业标签
     * @param array $data
     * @return bool
     */
    public function batchRemoveCorpTag(array $data): bool
    {
        $corpTagIds = json_decode($data['corp_tag_ids'], true);
        $ids = json_decode($data['ids'], true);

        $content = new ContactTcContentDto();
        $content->setContactIds($ids);
        $content->setRemoveTagIds($corpTagIds);

        return container()->get(ChContactTaskCenterService::class)->addTask($data['uid'],$data['main_uid'],ContactTaskCenterTyperConstants::DELETE_CORP_TAG,$content);
    }

    /**
     * 设置个人标签
     * @param array $data
     * @return bool
     */
    public function setPersonalTag(array $data): bool
    {
        $corpTagIds = json_decode($data['personal_tag_ids'], true);
        return $this->commonSetCorpTag($data['id'], $corpTagIds, 2);
    }


    /**
     * 通用设置企业标签
     * @param mixed $contactId
     * @param array $corpTagIds
     * @param int $labelType
     * @return bool
     */
    public function commonSetCorpTag(mixed $contactId, array $corpTagIds, int $labelType): bool
    {
        $contact = $this->mapper->findById($contactId);
        if (empty($contact)) {
            throw new NormalStatusException('请选择客户');
        }

        $robot = $this->robotMapper->findById($contact->robot_id);
        if(empty($robot) || $robot->login_status != 1){
            throw new NormalStatusException('请先登录企微号');
        }

        $allCorpTags = $contact->corpTags()->get();
        $beforeCorpTags = $allCorpTags->filter(function ($item) use ($labelType) {
            return $item['label_type'] == $labelType;
        })->map(function ($item) {
            return [
                'group_id' => $item['group_id'],
                'label_id' => $item['id'],
                'label_type' => $item['label_type']
            ];
        })->toArray();

        //删除
        $deletedTagIds = array_diff(array_column($beforeCorpTags, 'label_id'),$corpTagIds);
        //新增
        $addedTagIds  = array_diff($corpTagIds,array_column($beforeCorpTags, 'label_id'));
        if (!empty($beforeCorpTags) && empty($addedTagIds) && empty($deletedTagIds)) {
            return true;
        }

        // 获取最终的corpTags列表
        $finalCorpTags = $allCorpTags->filter(function ($item) use ($deletedTagIds) {
            // 移除被标记为删除的标签
            return !in_array($item['id'], $deletedTagIds);
        })->map(function ($item) {
            return [
                'group_id' => $item['group_id'],
                'label_id' => $item['id'],
                'label_type' => $item['label_type'],
                'owner_id' => $item['owner_id']
            ];
        })->toArray();

        // 如果有新增标签，需要查询并添加到最终列表中
        if (!empty($addedTagIds)) {
            $corpTagList = ChCorpTag::query()
                ->select(['id', 'group_id', 'corp_id', 'owner_id', 'label_type'])
                ->whereIn('id', $addedTagIds)
                ->get();

            $corpTagList = $corpTagList->map(function ($item) use ($labelType) {
                return [
                    'group_id' => $item['group_id'],
                    'label_id' => $item['id'],
                    'label_type' => $labelType,
                    'owner_id' => $item['owner_id']
                ];
            })->toArray();
            // 将新标签合并到最终标签列表中
            $finalCorpTags = array_merge($finalCorpTags, $corpTagList);
        }
        $finalCorpTags = array_values($finalCorpTags);

        $mobileList = ChContactMobile::query()->where('contact_id', $contact->id)->pluck('mobile')->toArray();
        $robotApiService = make(\App\Common\Robot\Robot::class, [$robot->server_id, $robot->uuid])->gateway();
        $desc = empty($contact->desc) ? '' : $contact->desc;
        $company_remark  = empty($contact->company_remark) ? '' : $contact->company_remark;
        $remark = empty($contact->remark) ? '' : $contact->remark;
        $robotApiService->updateWxContact(
            $contact->user_id,
            $remark,
            $desc,
            $company_remark,
            $mobileList,
            $finalCorpTags
        );
        $this->mapper->rmCache($contact->robot_id,$contact->user_id);
        //延迟3秒触发标签sop
        co(function () use ($contactId) {
            Coroutine::sleep(3);
            $contact = $this->mapper->findById($contactId);
            $this->eventDispatcher->dispatch(new SopTagTrigger($contact));
        });
        return true;
    }

    /**
     * 设置智能标签
     * @param array $data
     * @return bool
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function setSmartTag(array $data): bool
    {
        $contact = $this->mapper->findById($data['id']);
        if (empty($contact)) {
            throw new NormalStatusException('请选择客户');
        }
        $smartTagsIds = json_decode($data['smart_tag_ids'], true);
        $addTagIds = [];
        $removeTagIds = [];
        if ($data['type'] == 0) {
            $addTagIds = $smartTagsIds;
            $contact->smartTags()->attach($addTagIds);
        } else {
            $removeTagIds = $smartTagsIds;
            $contact->smartTags()->detach($removeTagIds);
        }
        container()->get(ChContactTaskCenterService::class)->updateSmartTagContactCnt([$contact->id], $addTagIds, $removeTagIds);
        return true;
    }

    /**
     * 批量设置智能标签
     * @param array $data
     * @return bool
     */
    public function batchSetSmartTag(array $data): bool
    {
        $corpTagIds = json_decode($data['smart_tag_ids'], true);
        $ids = json_decode($data['ids'], true);

        $content = new ContactTcContentDto();
        $content->setContactIds($ids);
        $content->setTagIds($corpTagIds);

        return container()->get(ChContactTaskCenterService::class)->addTask($data['uid'],$data['main_uid'],ContactTaskCenterTyperConstants::PUT_ON_SMART_TAG,$content);
    }

    /**
     * 批量移除智能标签
     * @param array $data
     * @return bool
     */
    public function batchRemoveSmartTag(array $data): bool
    {
        $corpTagIds = json_decode($data['smart_tag_ids'], true);
        $ids = json_decode($data['ids'], true);

        $content = new ContactTcContentDto();
        $content->setContactIds($ids);
        $content->setRemoveTagIds($corpTagIds);

        return container()->get(ChContactTaskCenterService::class)->addTask($data['uid'],$data['main_uid'],ContactTaskCenterTyperConstants::DELETE_SMART_TAG,$content);
    }

    /**
     * 批量修改备注
     * @param array $data
     * @return bool
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function batchEditRemark(array $data): bool
    {
        $ids = json_decode($data['ids'], true);

        $type = data_get($data,'type');
        $content = data_get($data,'content');
        $keyword = data_get($data,'keyword');
        $replace_text = data_get($data,'replace_text');

        $taskData = new ContactTcContentDto();
        $taskData->setContactIds($ids);
        $taskData->setExtra([
            'type' => $type,
            'content' => $content,
            'keyword' => $keyword,
            'replace_text' => $replace_text
        ]);

        return container()->get(ChContactTaskCenterService::class)->addTask($data['uid'],$data['main_uid'],ContactTaskCenterTyperConstants::EDIT_REMARK,$taskData);
    }

    /**
     * 批量修改备注
     * @param $contactId
     * @param array $data
     * @return bool
     */
    public function batchEditRemarkHandle($contactId,array $data): bool
    {
        $contact = $this->mapper->findById($contactId);
        if (empty($contact)) {
            return true;
        }

        $robotInfo = $this->robotMapper->findById($contact->robot_id);
        if (empty($robotInfo) || $robotInfo->login_status != 1) {
            return true;
        }

        if($data['type'] == 0){
            $content = $data['content'];
            $remark = TagReplacer::replaceTags($content,[
                'remark' => $contact->remark,
                'nickname' => $contact->nickname,
                'gender' => $contact->gender,
                'add_time' => datetime($contact->add_customer_time,'Y-m-d')
            ]);
        }else{
            if(empty($contact->remark) || !str_contains($contact->remark,$data['keyword'])){
                return true;
            }
            $remark = str_replace($data['keyword'],$data['replace_text'],$contact->remark);
        }

        $mobileList = ChContactMobile::query()->where('contact_id', $contact->id)->pluck('mobile')->toArray();
        $labelList = $contact->corpTags()->get();

        $labelList = $labelList->map(function ($item) {
            return [
                'group_id' => $item['group_id'],
                'label_id' => $item['id'],
                'label_type' => $item['label_type'],
                'owner_id' => $item['owner_id']
            ];
        })->toArray();

        $robotApiService = make(\App\Common\Robot\Robot::class, [$robotInfo->server_id, $robotInfo->uuid])->gateway();
        $desc = empty($contact->desc) ? '' : $contact->desc;
        $company_remark  = empty($contact->company_remark) ? '' : $contact->company_remark;
        $robotApiService->updateWxContact(
            $contact->user_id,
            $remark,
            $desc,
            $company_remark,
            $mobileList,
            $labelList
        );
        $this->mapper->rmCache($contact->robot_id,$contact->user_id);
        return  true;
    }

    /**
     * 根据手机号添加客户
     * @param int $id
     * @param int $robotId
     * @param string $mobile
     * @return bool
     */
    public function addContactByMobile(int $id,int $robotId,string $mobile): bool
    {
        $robot = $this->robotMapper->findById($robotId);
        if(empty($robot) || $robot->login_status != 1){
            return false;
        }

        $robotApiService = make(\App\Common\Robot\Robot::class, [$robot->server_id, $robot->uuid])->gateway();

        $result = $robotApiService->searchContact($mobile);

        if($result !== false && $result['search_status'] ==1 && !empty($result['wx_user_info'])){

            $wxUserInfo = $result['wx_user_info'];
            $unionId = $wxUserInfo['union_id'];
            $userId = $wxUserInfo['user_id'];

            Db::table('ch_add_friend')
                ->where('id',$id)
                ->update(['user_id'=>$userId]);

            $addResult = $robotApiService->addSearchWxContact($userId,$unionId);
            return $addResult !== false;
        }

        return false;
    }

    /**
     * 删除
     * @param array $params
     * @return bool
     */
    public function deleteContact(array $params): bool
    {
        $contact = $this->mapper->findById($params['id']);
        if(empty($contact)){
            throw new NormalStatusException('请选择客户');
        }

        $robotInfo = $this->robotMapper->findById($contact->robot_id);
        if(empty($robotInfo) || $robotInfo->login_status != 1){
            throw new NormalStatusException('请先登录企微号');
        }

        $robotService = make(\App\Common\Robot\Robot::class, [$robotInfo->server_id, $robotInfo->uuid])->gateway();
        $result = $robotService->deleteContact($contact->user_id);
        $this->mapper->rmCache($contact->robot_id,$contact->user_id);
        return $result !== false;
    }

    public function getExternalUserid(ChRobot $robotInfo,mixed $userId)
    {
        $contact = $this->mapper->findByRobotIdAndUserId($robotInfo->id,$userId);
        $corpInfo = container()->get(ChCorpMapper::class)->findById($robotInfo->corp_id);
        if(empty($contact)){
            return false;
        }
        if(empty($corpInfo->auth_corp_id)){
            logger()->info('获取企业corp_id失败-企业未授权');
            return false;
        }
        if(empty($contact->external_userid)){
            $OpenWorkService=new OpenWorkService($corpInfo->auth_corp_id);
            $service = make(\App\Common\Robot\Robot::class, [$robotInfo->server_id, $robotInfo->robot_key])->gateway();
            $result = $service->useridToOpenuserid([$userId]);
            $open_user_ids=$OpenWorkService->getNewExternalUserid(array_column($result,'open_user_id'));
            $external_userid=array_column($open_user_ids,'new_external_userid')[0];
            $contact->external_userid=$external_userid;
            $contact->save();
        }
        return $contact->external_userid;
    }
}